// 《围棋》作者版权所有。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package typebits

import (
	"cmd/compile/internal/base"
	"cmd/compile/internal/bitvec"
	"cmd/compile/internal/types"
)

// 注意：特定类型t的位图可以在
// 第一次运行后缓存在t中，然后简单地在正确的偏移量处复制到bv中
// 在以后使用相同类型t的调用中。
func Set(t *types.Type, off int64, bv bitvec.BitVec) {
	if uint8(t.Alignment()) > 0 && off&int64(uint8(t.Alignment())-1) != 0 {
		base.Fatalf("typebits.Set: invalid initial alignment: type %v has alignment %d, but offset is %v", t, uint8(t.Alignment()), off)
	}
	if !t.HasPointers() {
		// 注意：这种情况确保要去的指针：notinheap类型
		// 不被垃圾收集和堆栈复制视为指针。
		return
	}

	switch t.Kind() {
	case types.TPTR, types.TUNSAFEPTR, types.TFUNC, types.TCHAN, types.TMAP:
		if off&int64(types.PtrSize-1) != 0 {
			base.Fatalf("typebits.Set: invalid alignment, %v", t)
		}
		bv.Set(int32(off / int64(types.PtrSize))) // 指针

	case types.TSTRING:
		// 结构{byte*str；intgo len；}
		if off&int64(types.PtrSize-1) != 0 {
			base.Fatalf("typebits.Set: invalid alignment, %v", t)
		}
		bv.Set(int32(off / int64(types.PtrSize))) // 第一个插槽中的指针

	case types.TINTER:
		// 结构{Itab*选项卡；void*数据；}
		// 或者，当isnilinter（t）=true时：
		// 结构{Type*Type；void*data；}
		if off&int64(types.PtrSize-1) != 0 {
			base.Fatalf("typebits.Set: invalid alignment, %v", t)
		}
		// 接口的第一个字是指针，但我们不这样对待它。
		// 1。如果它是一个非空接口，指针指向一个itab 
		// 它总是在persistentalloc空间中。
		// 2。如果是空接口，指针将指向_类型。
		// a.如果是编译时分配的类型，则指向只读数据段。
		// b.如果是反射分配类型，则指向Go堆。
		// Reflect负责保留对基础类型
		// 的引用，因此它不会是GCd。
		// 如果我们有一个移动的GC，我们需要将其更改为2b（作为
		// 以及扫描itab以更新其itab.\u类型字段）。
		bv.Set(int32(off/int64(types.PtrSize) + 1)) // 第二个插槽中的指针

	case types.TSLICE:
		// 结构{byte*数组；uintgo len；uintgo cap；}
		if off&int64(types.PtrSize-1) != 0 {
			base.Fatalf("typebits.Set: invalid TARRAY alignment, %v", t)
		}
		bv.Set(int32(off / int64(types.PtrSize))) // 第一个插槽中的指针（位指针）

	case types.TARRAY:
		elt := t.Elem()
		if elt.Size() == 0 {
			// 对#20739短路。
			break
		}
		for i := int64(0); i < t.NumElem(); i++ {
			Set(elt, off, bv)
			off += elt.Size()
		}

	case types.TSTRUCT:
		for _, f := range t.Fields().Slice() {
			Set(f.Type, off+f.Offset, bv)
		}

	default:
		base.Fatalf("typebits.Set: unexpected type, %v", t)
	}
}
